home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / PNL Libraries / MyListWindow.p < prev    next >
Encoding:
Text File  |  1995-09-18  |  20.2 KB  |  810 lines  |  [TEXT/CWIE]

  1. unit MyListWindow;
  2.  
  3. interface
  4.  
  5.     uses
  6.         Lists, MyOOMainLoop;
  7.  
  8.     type
  9.         ListWindowObject = object(DObject)
  10.                 list: ListHandle;
  11.                 hcontrol: ControlHandle;
  12.                 list_offset, list_width, max_display_width, header_height: integer;
  13.                 typed_chars: str31;
  14.                 typed_time: longInt;
  15.                 procedure CreateList (font, size: integer; ldefID: integer; hscroll: boolean);
  16.                 procedure Destroy;
  17.                 override;
  18.                 procedure DoItemWhere (er: eventRecord; item: integer);
  19.                 override;
  20.                 procedure Resize;
  21.                 override;
  22.                 procedure DrawGrow;
  23.                 override;
  24.                 procedure DoActivateDeactivate (activate: boolean);
  25.                 override;
  26.                 procedure DoKey (modifiers: integer; ch: char; code: integer);
  27.                 override;
  28.                 procedure SelectAll (on: boolean);
  29.                 function Match (c: cell; var what: str255): boolean;
  30.                 procedure Find (what: str255; fromstart, allatonce, backwards: boolean);
  31.                 procedure AdjustHContol (canRedraw: BOOLEAN);
  32.                 procedure SetListWidth (max: integer);
  33.                 function DontDrag (er: EventRecord): boolean;
  34.                 function DoLClick (er: EventRecord): boolean;
  35.                 procedure DoDoubleClick;
  36.                 procedure DoDoubleClickCell (c: cell);
  37.                 function GetEntryName (c: cell): str255;
  38.                 function GetUniqueEntryName (c: cell): str255;
  39.                 procedure OpenParent;
  40.                 procedure LDEF (message: integer; select: boolean; var r: Rect; c: Cell; dataOffset, dataLen: integer);
  41.                 procedure DrawHeader (r: rect);
  42.                 procedure DoHeaderClick (r: rect; where: Point; modifiers: integer);
  43.                 procedure SetSingleSelection (v: integer);
  44.                 function SelectFirstAfter (s: str255): boolean;
  45.                 function SelectFirstBefore (s: str255): boolean;
  46.                 function GetFirstSelection (var c: Cell): boolean;
  47.                 function GetLastSelection (var c: Cell): boolean;
  48.                 function CountSelections: integer;
  49.                 function IsSelection: boolean;
  50.                 function DoSetupDragCell (c: cell; dragref: DragReference; dragrgn: RgnHandle): OSErr;
  51.                 function DoSetupDrag (dragref: DragReference; dragrgn: RgnHandle): OSErr;
  52.                 override;
  53.             end;
  54.  
  55.     procedure InitMyListWindow;
  56.     
  57. implementation
  58.  
  59.     uses
  60.         ToolUtils, Drag, 
  61.         MyDialogs, MyAssertions, MyTypes, MyMathUtils, MySystemGlobals, MyListManager, MyCursors, MyCallProc;
  62.  
  63.     const
  64.         list_item = 1;
  65.  
  66.     var
  67.         gDrawListProc : UniversalProcPtr;
  68.         gCallLDEFProc : UniversalProcPtr;
  69.         gMyClickLoopProc : UniversalProcPtr;
  70.         gHActionProc : UniversalProcPtr;
  71.         
  72.     procedure DrawList (dp: dialogPtr; item: integer);
  73.         var
  74.             r, rh: rect;
  75.             obj: ListWindowObject;
  76.     begin
  77.         SetPort(dp);
  78.         obj := ListWindowObject(GetWObject(dp));
  79.         PenNormal;
  80.         GetDItemRect(dp, item, r);
  81.         rh := r;
  82.         r.top := r.top + obj.header_height + 1;
  83.         InsetRect(r, -1, -1);
  84.         FrameRect(r);
  85.         if obj.header_height > 0 then begin
  86.             rh.bottom := rh.top + obj.header_height;
  87.             obj.DrawHeader(rh);
  88.         end;
  89.         obj.DrawGrow;
  90.         LUpdate(dp^.visRgn, obj.list);
  91.     end;
  92.  
  93.     procedure ListWindowObject.SelectAll (on: boolean);
  94.         var
  95.             i: integer;
  96.             c: cell;
  97.     begin
  98.         for i := 0 to list^^.databounds.bottom - 1 do begin
  99.             c.h := 0;
  100.             c.v := i;
  101.             LSetSelect(on, c, list);
  102.         end;
  103.     end;
  104.  
  105.     function ListWindowObject.Match (c: cell; var what: str255): boolean;
  106.     begin
  107.         c:=c; { UNUSED! }
  108.         what:=what; { UNUSED! }
  109.         Match := false;
  110.     end;
  111.  
  112.     procedure ListWindowObject.Find (what: str255; fromstart, allatonce, backwards: boolean);
  113.         var
  114.             c: cell;
  115.             found, found1: boolean;
  116.     begin
  117.         if allatonce then begin
  118.             found := false;
  119.             c.v := 0;
  120.             c.h := 0;
  121.             while (c.v < list^^.databounds.bottom) do begin
  122.                 found1 := Match(c, what);
  123.                 LSetSelect(found1, c, list);
  124.                 if found1 then begin
  125.                     found := true;
  126.                 end;
  127.                 c.v := c.v + 1;
  128.             end;
  129.         end
  130.         else begin
  131.             if backwards then begin
  132.                 if fromstart then begin
  133.                     c.v := list^^.databounds.bottom-1;
  134.                     c.h := 0;
  135.                 end else begin
  136.                     c.v := 0;
  137.                     c.h := 0;
  138.                     if LGetSelect(true, c, list) then begin
  139.                         c.v:=c.v-1;
  140.                     end else begin
  141.                         c.v := list^^.databounds.bottom-1;
  142.                         c.h := 0;
  143.                     end;
  144.                 end;
  145.                 found := false;
  146.                 while (c.v >=0) do begin
  147.                     found := Match(c, what);
  148.                     if found then begin
  149.                         leave;
  150.                     end;
  151.                     c.v := c.v - 1;
  152.                 end;
  153.             end else begin
  154.                 c.v := 0;
  155.                 c.h := 0;
  156.                 if not fromstart then begin
  157.                     while LGetSelect(true, c, list) do begin
  158.                         c.v := c.v + 1;
  159.                         c.h := 0;
  160.                     end;
  161.                 end;
  162.                 found := false;
  163.                 while (c.v < list^^.databounds.bottom) do begin
  164.                     found := Match(c, what);
  165.                     if found then begin
  166.                         leave;
  167.                     end;
  168.                     c.v := c.v + 1;
  169.                 end;
  170.             end;
  171.             if found then begin
  172.                 SetSingleSelection(c.v);
  173.             end;
  174.         end;
  175.         if not found then begin
  176.             SysBeep(1);
  177.         end;
  178.     end;
  179.  
  180.     procedure ListWindowObject.LDEF (message: integer; select: boolean; var r: Rect; c: Cell; dataOffset, dataLen: integer);
  181.     begin
  182.         message:=message; { UNUSED! }
  183.         select:=select; { UNUSED! }
  184.         r:=r; { UNUSED! }
  185.         c:=c; { UNUSED! }
  186.         dataOffset:=dataOffset; { UNUSED! }
  187.         dataLen:=dataLen; { UNUSED! }
  188.     end;
  189.  
  190.     procedure ListWindowObject.DrawHeader (r: rect);
  191.     begin
  192.         r:=r; { UNUSED! }
  193.     end;
  194.  
  195.     procedure ListWindowObject.DoHeaderClick (r: rect; where: Point; modifiers: integer);
  196.     begin
  197.         r:=r; { UNUSED! }
  198.         where:=where; { UNUSED! }
  199.         modifiers:=modifiers; { UNUSED! }
  200.     end;
  201.  
  202.     procedure CallLDEF (message: integer; select: boolean; var r: Rect; c: Cell; dataOffset, dataLen: integer; lh: ListHandle);
  203.         var
  204.             obj:WObject; { BUG IN MWP }
  205.     begin
  206.         obj:=GetWObject(lh^^.port);
  207.         ListWindowObject(obj).LDEF(message, select, r, c, dataOffset, dataLen);
  208.     end;
  209.  
  210.     procedure ListWindowObject.SetListWidth (max: integer);
  211.     begin
  212.         list_width := max;
  213.         zoomSize.h := max + 16;
  214.         zoomSize.v := list^^.cellSize.v * (list^^.dataBounds.bottom) + 16 + header_height;
  215.         AdjustHContol(true);
  216.     end;
  217.  
  218.     procedure ListWindowObject.AdjustHContol (canRedraw: BOOLEAN);
  219. {Calculate the new control maximum value and current value }
  220. {max is calculated by comparing the maximum document}
  221. {width to the width of the viewRect. The current values are set by comparing the offset between}
  222. {the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by}
  223. {calling ShowControl.}
  224.         var
  225.             max: INTEGER;
  226.             oldValue, oldMax: INTEGER;
  227.             cliprgn: RgnHandle;
  228.             r: rect;
  229.     begin
  230.         oldValue := GetControlValue(hcontrol);
  231.         oldMax := GetControlMaximum(hcontrol);
  232.         GetDItemRect(window, list_item, r);
  233.         max := list_width - (r.right - 16 - r.left);
  234.         if max < 0 then begin
  235.             max := 0;            {check for negative values}
  236.         end;
  237.         list_offset := Pin(0, oldValue, max);
  238.         SetPort(window);
  239.         clipRgn := NewRgn;
  240.         GetClip(clipRgn);
  241.         SetRect(r, 0, 0, 0, 0);
  242.         ClipRect(r);
  243.         SetControlMaximum(hcontrol, max);
  244.         SetClip(clipRgn);
  245.         DisposeRgn(clipRgn);
  246.         SetControlValue(hcontrol, list_offset);
  247.         if canRedraw and ((max <> oldMax) or (list_offset <> oldValue)) then begin
  248.             ShowControl(hcontrol);            {check to see if the control can be re-drawn}
  249.         end;
  250.     end;
  251.  
  252.     procedure ListWindowObject.CreateList (font, size: integer; ldefID: integer; hscroll: boolean);
  253.         var
  254.             view, bounds: rect;
  255.             siz: point;
  256.             k: integer;
  257.             h: handle;
  258.             fi: FontInfo;
  259.             dr: rect;
  260.     begin
  261.         handle_shift_tab := false;
  262.         typed_time := 0;
  263.         max_display_width := maxInt;
  264.         header_height := 0;
  265.         SetPort(window);
  266.         TextFont(font);
  267.         TextSize(size);
  268.         GetFontInfo(fi);
  269.         draw_grow_icon := true;
  270.         GetDialogItem(window, list_item, k, h, view);
  271.         SetDialogItem(window, list_item, k, handle(gDrawListProc), view);
  272.         SetRect(bounds, 0, 0, 1, 0);
  273.         view.right := view.right - 15;
  274.         SetPt(siz, 30000, fi.ascent + fi.descent + fi.leading);
  275.         list := LNew(view, bounds, siz, ldefID, window, true, true, false, true);
  276.         list^^.refcon := longInt(gCallLDEFProc);
  277.         if hscroll then begin
  278.             SetRect(dr, 0, 0, 100, 16);
  279.             hcontrol := NewControl(window, dr, '', true, 0, 0, 0, scrollBarProc, 0);
  280.         end
  281.         else begin
  282.             hcontrol := nil;
  283.         end;
  284.         Resize;
  285.     end;
  286.  
  287.     procedure ListWindowObject.Destroy;
  288.     begin
  289.         LDispose(list);
  290.         inherited Destroy;
  291.     end;
  292.  
  293.     procedure ListWindowObject.DoDoubleClickCell (c: cell);
  294.     begin
  295.         c:=c; { UNUSED! }
  296.     end;
  297.  
  298.     function ListWindowObject.DoSetupDragCell (c: cell; dragref: DragReference; dragrgn: RgnHandle): OSErr;
  299.     begin
  300.         c:=c; { UNUSED! }
  301.         dragref:=dragref; { UNUSED! }
  302.         dragrgn:=dragrgn; { UNUSED! }
  303.         DoSetupDragCell := -1;
  304.     end;
  305.  
  306.     function ListWindowObject.DoSetupDrag (dragref: DragReference; dragrgn: RgnHandle): OSErr;
  307.         var
  308.             c: Cell;
  309.             err: OSErr;
  310.     begin
  311.         err := -23;
  312.         c.h := 0;
  313.         c.v := 0;
  314.         while LGetSelect(true, c, list) do begin
  315.             err := DoSetupDragCell(c, dragref, dragrgn);
  316.             if err <> noErr then begin
  317.                 leave;
  318.             end;
  319.             c.v := c.v + 1;
  320.             c.h := 0;
  321.         end;
  322.         DoSetupDrag := err;
  323.     end;
  324.  
  325.     var
  326.         CLFirstCall: boolean;
  327.         CLFirstPt: Point;
  328.         CLlist: ListHandle;
  329.         CLer: EventRecord;
  330.         CLwobj: WObject;
  331.  
  332.     function MyClickLoop: boolean;
  333.         var
  334.             r, cellRect: rect;
  335.             cellClicked: Cell;
  336.             curPt: Point;
  337.             dummy: boolean;
  338.             ret: boolean;
  339.     begin
  340.         ret := true;
  341.         if CLFirstCall then begin
  342.             CLFirstCall := false;
  343.             GetMouse(CLFirstPt);
  344.         end else begin
  345.             SetRect(r, CLfirstPt.h - 3, CLfirstPt.v - 3, CLfirstPt.h + 3, CLfirstPt.v + 3);
  346.             cellClicked := LLastClick(CLlist);
  347.             LRect(cellRect, cellClicked, CLlist);
  348.             dummy := SectRect(r, cellRect, r);
  349.             GetMouse(curPt);
  350.             if not PtInRect(curPt, r) then begin
  351. { DebugStr('MyClickLoop Drag;g'); }
  352.                 CLwobj.DoTrackDrag(CLer);
  353.                 ret := false;
  354.             end;
  355.         end;
  356.         MyClickLoop := ret;
  357.     end;
  358.  
  359.     function ListWindowObject.DontDrag (er: EventRecord): boolean;
  360.     begin
  361.         er:=er; { UNUSED! }
  362.         DontDrag := last_event_had_shift or last_event_had_command;
  363.     end;
  364.  
  365.     function ListWindowObject.DoLClick (er: EventRecord): boolean;
  366.         var
  367.             double: boolean;
  368.             savedcl: ProcPtr;
  369.             local: Point;
  370.     begin
  371.         local := er.where;
  372.         GlobalToLocal(local);
  373. { DebugStr('ListWindowObject.DontDrag;g'); } 
  374.         if not has_DragManager or DontDrag(er) then begin
  375. { DebugStr('ListWindowObject.DontDrag NOT!;g'); } 
  376.             CursorSetProcessing(false);
  377.             double := LClickSafe(local, er.modifiers, list);
  378.         end
  379.         else begin
  380. { DebugStr('ListWindowObject.DontDrag YES!;g'); }
  381.             savedcl := list^^.lClickLoop;
  382.             list^^.lClickLoop := gMyClickLoopProc;
  383.             CLFirstCall := true;
  384.             CLlist := list;
  385.             CLer := er;
  386.             CLwobj := self;
  387.             CursorSetProcessing(false);
  388.             double := LClickSafe(local, er.modifiers, list);
  389.             list^^.lClickLoop := savedcl;
  390.         end;
  391.         DoLClick := double;
  392.     end;
  393.  
  394.     procedure ListWindowObject.OpenParent;
  395.     begin
  396.     end;
  397.  
  398.     procedure ListWindowObject.SetSingleSelection (v: integer);
  399.     begin
  400.         LSetSingleSelection(list, v);
  401.         LAutoScroll(list);
  402.     end;
  403.  
  404.     procedure ListWindowObject.DoDoubleClick;
  405.         var
  406.             c: Cell;
  407.     begin
  408.         c.h := 0;
  409.         c.v := 0;
  410.         while LGetSelect(true, c, list) do begin
  411.             DoDoubleClickCell(c);
  412.             c.v := c.v + 1;
  413.             c.h := 0;
  414.         end;
  415.     end;
  416.  
  417.     var
  418.         action_listobj: ListWindowObject;
  419.  
  420.     procedure CommonAction (control: ControlHandle; var amount: integer);
  421.         var
  422.             value, max, ovalue: integer;
  423.     begin
  424.         value := GetControlValue(control);
  425.         ovalue := value;
  426.         max := GetControlMaximum(control);
  427.         value := Pin(0, value - amount, max);
  428.         if value <> ovalue then begin
  429.             SetControlValue(control, value);
  430.         end;
  431.         amount := ovalue - value;   { calculate true change }
  432.     end; { CommonAction  }
  433.  
  434. { Determines how much to change the value of the horizontal scrollbar by and how }
  435. { much to scroll the TE record. }
  436.     procedure HAction (control: ControlHandle; part: integer);
  437.         var
  438.             amount: integer;
  439.             window: WindowPtr;
  440.     begin
  441.         if (part <> 0) then begin
  442.             window := action_listobj.window;
  443.             case part of
  444.                 kControlUpButtonPart, kControlDownButtonPart:    begin    { a few pixels }
  445.                     amount := 8;
  446.                 end;
  447.                 kControlPageUpPart, kControlPageDownPart: begin        { a page width }
  448.                     with action_listobj.list^^.rView do begin
  449.                         amount := (right - left);
  450.                     end;
  451.                 end;
  452.             end;
  453.             if ((part = kControlDownButtonPart) or (part = kControlPageDownPart)) then begin
  454.                 amount := -amount;        { reverse direction }
  455.             end;
  456.             CommonAction(control, amount);
  457.             if amount <> 0 then begin
  458.                 action_listobj.list_offset := GetControlValue(control);
  459.                 DrawList(window, list_item);
  460.             end;
  461.         end;
  462.     end;
  463.  
  464.     function ListWindowObject.GetEntryName (c: cell): str255;
  465.     begin
  466.         c:=c; { UNUSED! }
  467.         GetEntryName := '';
  468.     end;
  469.  
  470.     function ListWindowObject.GetUniqueEntryName (c: cell): str255;
  471.     begin
  472.         GetUniqueEntryName := concat(GetEntryName(c), chr(0), chr(c.v div 256), chr(c.v mod 256));
  473.     end;
  474.  
  475.     function ListWindowObject.SelectFirstAfter (s: str255): boolean;
  476.         var
  477.             i, index: integer;
  478.             c: Cell;
  479.             best, n: str255;
  480.             good: boolean;
  481.     begin
  482.         good := false;
  483.         best := concat(chr(255), chr(255));
  484.         for i := 0 to list^^.databounds.bottom - 1 do begin
  485.             c.h := 0;
  486.             c.v := i;
  487.             n := GetUniqueEntryName(c);
  488.             if (IUCompString(s, n) < 0) & (IUCompString(n, best) < 0) then begin
  489.                 best := n;
  490.                 index := c.v;
  491.                 good := true;
  492.             end;
  493.         end;
  494.         if good then begin
  495.             SetSingleSelection(index);
  496.         end;
  497.         SelectFirstAfter := good;
  498.     end;
  499.  
  500.     function ListWindowObject.SelectFirstBefore (s: str255): boolean;
  501.         var
  502.             i, index: integer;
  503.             c: Cell;
  504.             best, n: str255;
  505.             good: boolean;
  506.     begin
  507.         good := false;
  508.         index := 0;
  509.         best := '';
  510.         for i := 0 to list^^.databounds.bottom - 1 do begin
  511.             c.h := 0;
  512.             c.v := i;
  513.             n := GetUniqueEntryName(c);
  514.             if (IUCompString(s, n) > 0) & (IUCompString(n, best) > 0) then begin
  515.                 best := n;
  516.                 index := c.v;
  517.                 good := true;
  518.             end;
  519.         end;
  520.         if good then begin
  521.             SetSingleSelection(index);
  522.         end;
  523.         SelectFirstBefore := good;
  524.     end;
  525.  
  526.     function ListWindowObject.GetFirstSelection (var c: Cell): boolean;
  527.         var
  528.             best, n: str255;
  529.             index: integer;
  530.     begin
  531.         GetFirstSelection := false;
  532.         c.h := 0;
  533.         c.v := 0;
  534.         best := concat(chr(255), chr(255));
  535.         while LGetSelect(true, c, list) do begin
  536.             GetFirstSelection := true;
  537.             n := GetUniqueEntryName(c);
  538.             if IUCompString(n, best) < 0 then begin
  539.                 index := c.v;
  540.             end;
  541.             c.v := c.v + 1;
  542.         end;
  543.         c.h := 0;
  544.         c.v := index;
  545.     end;
  546.  
  547.     function ListWindowObject.GetLastSelection (var c: Cell): boolean;
  548.         var
  549.             best, n: str255;
  550.             index: integer;
  551.     begin
  552.         GetLastSelection := false;
  553.         c.h := 0;
  554.         c.v := 0;
  555.         best := '';
  556.         while LGetSelect(true, c, list) do begin
  557.             GetLastSelection := true;
  558.             n := GetUniqueEntryName(c);
  559.             if IUCompString(n, best) > 0 then begin
  560.                 index := c.v;
  561.             end;
  562.             c.v := c.v + 1;
  563.         end;
  564.         c.h := 0;
  565.         c.v := index;
  566.     end;
  567.  
  568.     procedure ListWindowObject.DoKey (modifiers: integer; ch: char; code: integer);
  569.         var
  570.             c: Cell;
  571.             index: integer;
  572.             dummy: boolean;
  573.             onlyoneselection: boolean;
  574.     begin
  575.         modifiers:=modifiers; { UNUSED! }
  576.         code:=code; { UNUSED! }
  577.         onlyoneselection := BAND(list^^.selFlags, lOnlyOne) <> 0;
  578.         if ch < ' ' then begin
  579.             typed_time := 0;
  580.         end;
  581.         case ord(ch) of
  582.             downArrowChar:  begin
  583.                 if last_event_had_command then begin
  584.                     DoDoubleClick;
  585.                 end
  586.                 else begin
  587.                     if list^^.dataBounds.bottom > 0 then begin
  588.                         if LGetLastSelection(list, c) then begin
  589.                             index := c.v + 1;
  590.                         end
  591.                         else begin
  592.                             index := 0;
  593.                         end;
  594.                         if index >= list^^.dataBounds.bottom then begin
  595.                             index := list^^.dataBounds.bottom - 1;
  596.                         end;
  597.                         if onlyoneselection or not last_event_had_shift then begin
  598.                             SetSingleSelection(index);
  599.                         end
  600.                         else begin
  601.                             c.v := index;
  602.                             LSetSelect(true, c, list);
  603.                         end;
  604.                     end;
  605.                 end;
  606.             end;
  607.             upArrowChar:  begin
  608.                 if last_event_had_command then begin
  609.                     OpenParent;
  610.                 end
  611.                 else begin
  612.                     if list^^.dataBounds.bottom > 0 then begin
  613.                         if not LGetFirstSelection(list, c) then begin
  614.                             c.v := list^^.dataBounds.bottom;
  615.                         end;
  616.                         c.v := c.v - 1;
  617.                         if c.v < 0 then begin
  618.                             c.v := 0;
  619.                         end;
  620.                         if onlyoneselection or not last_event_had_shift then begin
  621.                             SetSingleSelection(c.v);
  622.                         end
  623.                         else begin
  624.                             LSetSelect(true, c, list);
  625.                         end;
  626.                     end;
  627.                 end;
  628.             end;
  629.             homeChar:  begin
  630.                 LScroll(0, -list^^.dataBounds.bottom, list);
  631.             end;
  632.             endChar:  begin
  633.                 LScroll(0, list^^.dataBounds.bottom, list);
  634.             end;
  635.             pageUpChar:  begin
  636.                 LScroll(0, -(list^^.visible.bottom - list^^.visible.top - 2), list);
  637.             end;
  638.             pageDownChar:  begin
  639.                 LScroll(0, (list^^.visible.bottom - list^^.visible.top - 2), list);
  640.             end;
  641.             tabChar:  begin
  642.                 if last_event_had_shift then begin
  643.                     if not GetFirstSelection(c) | not SelectFirstBefore(GetUniqueEntryName(c)) then begin
  644.                         dummy := SelectFirstBefore(chr(255));
  645.                     end;
  646.                 end
  647.                 else begin
  648.                     if not GetLastSelection(c) | not SelectFirstAfter(GetUniqueEntryName(c)) then begin
  649.                         dummy := SelectFirstAfter('');
  650.                     end;
  651.                 end;
  652.             end;
  653.             3, 13:  begin
  654.                 DoDoubleClick;
  655.             end;
  656.             otherwise begin
  657.                 if ch >= ' ' then begin
  658.                     if last_event_time - typed_time > 60 then begin
  659.                         typed_chars := '';
  660.                     end;
  661.                     typed_time := last_event_time;
  662.                     typed_chars := concat(typed_chars, ch);
  663.                     if not SelectFirstAfter(typed_chars) then begin
  664.                         dummy := SelectFirstBefore(chr(255));
  665.                     end;
  666.                 end;
  667.             end;
  668.         end;
  669. { WARNING: self may have been destroyed! }
  670.     end;
  671.  
  672.     procedure ListWindowObject.DoItemWhere (er: eventRecord; item: integer);
  673.         var
  674.             didit: boolean;
  675.             ctl: ControlHandle;
  676.             part, value: integer;
  677.             r: rect;
  678.             local: Point;
  679.     begin
  680.         case item of
  681.             list_item:  begin
  682.                 SetPort(window);
  683.                 local := er.where;
  684.                 GlobalToLocal(local);
  685.                 if local.v < header_height then begin
  686.                     GetDItemRect(window, list_item, r);
  687.                     r.bottom := r.top + header_height;
  688.                     DoHeaderClick(r, local, er.modifiers);
  689.                 end
  690.                 else begin
  691.                     didit := false;
  692.                     if hcontrol <> nil then begin
  693.                         part := FindControl(local, window, ctl);
  694.                         if ctl = hcontrol then begin
  695.                             didit := true;
  696.                             if part = kControlIndicatorPart then begin
  697.                                 value := GetControlValue(hcontrol);
  698.                                 part := TrackControl(hcontrol, local, nil);
  699.                                 if part <> 0 then begin
  700.                                     list_offset := GetControlValue(hcontrol);
  701.                                     if value <> list_offset then begin
  702.                                         InvalRect(window^.portRect);
  703.                                     end;
  704.                                 end;
  705.                             end
  706.                             else begin
  707.                                 action_listobj := self;
  708.                                 value := TrackControl(hcontrol, local, gHActionProc);
  709.                             end;
  710.  
  711.                         end;
  712.                     end;
  713.                     if not didit & DoLClick(er) then begin
  714.                         DoDoubleClick;
  715.                     end;
  716.                 end;
  717.             end;
  718.             otherwise
  719.                 inherited DoItemWhere(er, item);
  720.         end;
  721.     end;
  722.  
  723.     procedure ListWindowObject.DoActivateDeactivate (activate: boolean);
  724.     begin
  725.         LActivate(activate, list);
  726.         if hcontrol <> nil then begin
  727.             if activate then begin
  728.                 ShowControl(hcontrol);
  729.             end
  730.             else begin
  731.                 HideControl(hcontrol);
  732.             end;
  733.         end;
  734.         inherited DoActivateDeactivate(activate);
  735.     end;
  736.  
  737.     procedure ListWindowObject.Resize;
  738.         const
  739.             invis = 0;
  740.             vis = 255;
  741.         var
  742.             r: rect;
  743.             width, height, nheight, lineheight: integer;
  744.     begin
  745.         SetPort(window);
  746.         lineheight := list^^.cellSize.v;
  747.         width := window^.portrect.right - window^.portrect.left;
  748.         height := window^.portrect.bottom - window^.portrect.top;
  749.         nheight := (height - header_height - 16) mod lineheight;
  750.         if nheight <> 0 then begin
  751.             SizeWindow(window, width, height - nheight, false);
  752.         end;
  753.         growRect.top := (50 + lineheight - 1) div lineheight * lineheight + header_height + 16;
  754.         r.left := 0;
  755.         r.right := window^.portrect.right + 1;
  756.         if r.right > max_display_width then begin
  757.             r.right := max_display_width;
  758.         end;
  759.         r.top := 0;
  760.         r.bottom := window^.portrect.bottom;
  761.         SetDItemRect(window, list_item, r);
  762.         r.top := r.top + header_height + 1;
  763.         r.bottom := r.bottom - 15;
  764.         height := r.bottom - r.top;
  765.         list^^.rView.topleft := r.topleft; { LMove???? }
  766.         LSize(r.right - r.left - 16, height, list);
  767.         if hcontrol <> nil then begin
  768.             hcontrol^^.contrlVis := invis;
  769.             MoveControl(hcontrol, r.left, r.bottom);
  770.             SizeControl(hcontrol, r.right - r.left - 15, 16);
  771.             AdjustHContol(false);
  772.             hcontrol^^.contrlVis := vis;
  773.         end;
  774.         zoomSize.v := list^^.cellSize.v * (list^^.dataBounds.bottom) + 16 + header_height;
  775.         InvalRect(window^.portRect);
  776.         inherited Resize;
  777.     end;
  778.  
  779.     procedure ListWindowObject.DrawGrow;
  780.         var
  781.             r: rect;
  782.     begin
  783.         SetRect(r, -30000, header_height + 1, 30000, 30000);
  784.         DrawTheFriggingGrowIcon(window, r);
  785.     end;
  786.  
  787.     function ListWindowObject.CountSelections: integer;
  788.     begin
  789.         CountSelections := LCountSelections(list);
  790.     end;
  791.  
  792.     function ListWindowObject.IsSelection: boolean;
  793.     begin
  794.         IsSelection := LHasSelection(list);
  795.     end;
  796.  
  797.     procedure InitMyListWindow;
  798.     begin
  799.         gDrawListProc := NewUserItemProc(@DrawList);
  800.         gCallLDEFProc := NewListDefProc(@CallLDEF);
  801.         gMyClickLoopProc := NewProc(@MyClickLoop, uppListClickLoopProcInfo);
  802.         gHActionProc := NewControlActionProc(@HAction);
  803.     end;
  804.     
  805. end.
  806.     function MyClickLoop: boolean; { returns the bloody equal flag for gods sake! }
  807.     begin
  808.         MyClickLoop := MyClickLoop2; { BE VERY CAREFUL!  Returns the equal flag! }
  809.     end;
  810.